/**
 * @file logger.h
 * @brief Logger class interface
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 3 of the License.
 *
 * @author VestniK (Sergey N.Vidyuk) sir.vestnik@gmail.com
 * @date 16 Jan 2010
 */

#ifndef MJN_LOGGER_H
#define MJN_LOGGER_H

#include <QtCore/QObject>
#include <QtCore/QString>
#include <QtCore/QDateTime>
#include <QtCore/QIODevice>
#include <QtCore/QSharedData>
#include <QtCore/QSharedDataPointer>
#include <QtCore/QSharedPointer>
#include <QtCore/QMutex>
#include <QtCore/QThread>
#include <QtCore/QMetaType>

namespace mjn {

    class LogMessage;

    class Logger : public QObject {
        Q_OBJECT
        public:
            virtual ~Logger() {};
            static Logger *instance();

            enum Severity {Error,Info,Debug};
            enum Type {Network,Protocol,Session,Game,Other};

            void setDevice(QIODevice *device) {mDevice = device;}
            QIODevice *device() {return mDevice;}

            void error(Type type,const QString &msg);
            void info(Type type,const QString &msg);
            void debug(Type type,const QString &msg);
        protected:
            virtual void log(Severity severity,
                             Type type,
                             const QString &msg,
                             QThread *thread);
            virtual void writeMsg(const LogMessage &msg);
        signals:
            void newMessage(LogMessage);
        private:
            explicit Logger(QObject *parent = 0);

            QIODevice *mDevice;
            static QSharedPointer<Logger> mInstance;
            static QMutex mMutex;
    };

    /// @brief Helper shortcut to access logger instance
    inline Logger *log() {return Logger::instance();}

    class LogMessageData: public QSharedData{
        public:
            LogMessageData();
            LogMessageData(const QString& msg);
            LogMessageData(const LogMessageData &other);
            virtual ~LogMessageData() {};

            QDateTime time;
            QString message;
            Logger::Severity severity;
            Logger::Type type;
    };

    class LogMessage {
        public:
            LogMessage() {d = new LogMessageData;}
            LogMessage(const QString &msg): d(new LogMessageData(msg)) {}
            LogMessage(const LogMessage &message): d(message.d) {}

            const QDateTime &time() const {return d->time;}
            const QString &message() const {return d->message;}
            Logger::Severity severity() const {return d->severity;}
            Logger::Type type() const {return d->type;}

            void setTime(const QDateTime &time) {d->time = time;}
            void setMessage(const QString &message) {d->message = message;}
            void setSeverity(Logger::Severity severity) {d->severity = severity;}
            void setType(Logger::Type type) {d->type = type;}
        private:
            QSharedDataPointer<LogMessageData> d;
    };

}

Q_DECLARE_METATYPE(mjn::LogMessage);

#endif // MJN_LOGGER_H
